package menu

import (
	"encoding/json"
	"time"

	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/liu-cn/json-filter/filter"
	"github.com/y2h/fyne_poem/widgets"
)

//For the same structure, you may want to return only uid and avatar nickname fields under the article interface. Other fields do not want to be exposed

//In addition, you also want to return the four fields of nickname sex vipendtime price under the profile interface. Other fields do not want to be exposed

//There are many such situations. If you want to reuse a structure to construct the JSON data structure you want, you can see a simple demo

type User struct {
	UID    uint   `json:"uid,select(article)"`    //elect indicates the selected scene (the case that this field will use)
	Avatar string `json:"avatar,select(article)"` //As above, this field will only be resolved when the article interface

	Nickname string `json:"nickname,select(article|profile)"` //"｜"It means that this field is required for multiple cases. The article interface and the profile interface are also required

	Sex        int       `json:"sex,select(profile)"`          //This field is only used by profile
	VipEndTime time.Time `json:"vip_end_time,select(profile)"` //ditto
	Price      string    `json:"price,select(profile)"`        //ditto
}

func jsonfilter() {
	w := widgets.EmptyWin("json filter")
	msg := widget.NewLabel("")
	user := User{
		UID:        1,
		Nickname:   "boyan",
		Avatar:     "avatar",
		Sex:        1,
		VipEndTime: time.Now().Add(time.Hour * 24 * 365),
		Price:      "999.9",
	}

	left := widget.NewMultiLineEntry()
	right := widget.NewMultiLineEntry()
	user0 := NewUser()
	btn0 := widget.NewButton("user article", func() {
		marshal, err := json.Marshal(user)
		if err != nil {
			msg.SetText(err.Error())
		}
		gj0,_:=gjson.LoadContent(marshal)
		left.SetText(gj0.MustToJsonIndentString())
		//The following is the official JSON parsing output: you can see that all fields have been parsed
		//{"uid":1,"nickname":"boyan","avatar":"avatar","sex":1,"vip_end_time":"2023-03-06T23:11:22.622693+08:00","price":"999.9"}

		//usage：filter.SelectMarshal("select case",This can be：slice/array/struct/pointer/map)
		gj1, _ := gjson.LoadContent(filter.SelectMarshal("article", user).MustJSON())
		right.SetText(gj1.MustToJsonIndentString())
		 //The following is the JSON filtered by JSON filter. This output is the JSON under the article interface
		//{"avatar":"avatar","nickname":"boyan","uid":1}
	})
	btn01 := widget.NewButton("user article", func() {
		marshal, err := json.Marshal(user)
		if err != nil {
			msg.SetText(err.Error())
		}
		gj0,_:=gjson.LoadContent(marshal)
		left.SetText(gj0.MustToJsonIndentString())
		//The following is the official JSON parsing output: you can see that all fields have been parsed
		//{"uid":1,"nickname":"boyan","avatar":"avatar","sex":1,"vip_end_time":"2023-03-06T23:11:22.622693+08:00","price":"999.9"}

		gj1, _ := gjson.LoadContent(filter.SelectMarshal("profile", user).MustJSON())
		right.SetText(gj1.MustToJsonIndentString())
		//profile result
		//{"nickname":"boyan","price":"999.9","sex":1,"vip_end_time":"2023-03-06T23:31:28.636529+08:00"}
	})
	btn1 := widget.NewButton("lang", func() {
		jsonStr, _ := json.Marshal(user0)
		gj0,_:=gjson.LoadContent(jsonStr)
		left.SetText(gj0.MustToJsonIndentString())
		lang := filter.SelectMarshal("lang", user0)
		gj1, _ := gjson.LoadContent(lang.MustJSON())
		right.SetText(gj1.MustToJsonIndentString())
	})
	btn2 := widget.NewButton("lookup", func() {
		jsonStr, _ := json.Marshal(user0)
		gj0,_:=gjson.LoadContent(jsonStr)
		left.SetText(gj0.MustToJsonIndentString())
		lookup := filter.SelectMarshal("lookup", user0)
		gj1, _ := gjson.LoadContent(lookup.MustJSON())
		right.SetText(gj1.MustToJsonIndentString())
	})
	split := container.NewHSplit(left, right)
	w.SetContent(container.NewBorder(nil,
		msg, container.NewVBox(btn0, btn01, btn1, btn2), nil, split))
	w.Show()
}

type Users struct {
	UID          uint   `json:"uid,select($any)"`
	Name         string `json:"name,select(comment|chat|profile|justName)"`
	Age          int    `json:"age,select(comment|chat|profile)"`
	Avatar       string `json:"avatar,select(comment|chat|profile)"`
	Birthday     int    `json:"birthday,select(profile)"`
	Password     string `json:"password"`
	PasswordSlat string `json:"password_slat"`
	LangAge      []Lang `json:"langAge,select(profile|lookup|lang)"`
}

type Lang struct {
	Name string `json:"name,select(profile|lang)"`
	Arts []*Art `json:"arts,select(profile|lookup)"`
}

type Art struct {
	Name    string                 `json:"name,select(profile)"`
	Profile map[string]interface{} `json:"profile,select(profile|lookup)"`
	Values  []string               `json:"values,select(profile|lookup)"`
}

func NewUser() Users {
	return Users{
		UID:          1,
		Name:         "boyan",
		Age:          20,
		Avatar:       "https://www.avatar.com",
		Birthday:     2001,
		PasswordSlat: "slat",
		Password:     "123",
		LangAge: []Lang{
			{
				Name: "c",
				Arts: []*Art{
					{
						Name: "cc",
						Profile: map[string]interface{}{
							"c": "clang",
						},
						Values: []string{"1", "2"},
					},
				},
			},
			{
				Name: "c++",
				Arts: []*Art{
					{
						Name: "c++",
						Profile: map[string]interface{}{
							"c++": "cpp",
						},
						Values: []string{"cpp1", "cpp2"},
					},
				},
			},
			{
				Name: "Go",
				Arts: []*Art{
					{
						Name: "Golang",
						Profile: map[string]interface{}{
							"Golang": "go",
						},
						Values: []string{"Golang", "Golang1"},
					},
				},
			},
		},
	}
}
